<?php

namespace app\common\biz\list;

use \app\common\enum\SearchType as SearchTypeEnum;

/**
 * 查询类
 */
class Search
{
    private static array $keyword = ['field', 'sort', 'order', 'page', 'page_size'];
    private string $field = '';
    private array $params = [];
    private array $order = [];
    private int $page = 0;
    private int $pageSize = 0;

    private array $searchParams;
    private ?SearchType $searchType;


    public function __construct(array $search = [], SearchType $searchType = null)
    {
        $this->searchParams = $search;
        $this->searchType = $searchType;
        $this->parse();
    }

    public function setField(string $field): void
    {
        $this->field = $field;
    }

    public function getField(): string
    {
        $field = p('field');
        empty($field) && $field = SearchTypeEnum::FieldAll->value;
        if (SearchTypeEnum::FieldAll->value !== $field && !empty($this->field)) {
            $inputField = explode(',', $field);
            $innerField = explode(',', $this->field);
            $tmpField = [];
            foreach ($inputField as $str) {
                if (in_array($str, $innerField)) {
                    $tmpField[] = $str;
                }
            }
            $this->field = empty($tmpField) ? $this->field : implode(',', $tmpField);
        }

        return empty($this->field) ? $field : $this->field;
    }

    public function setOrder(string $name, string $order = SearchTypeEnum::OrderDesc->value): void
    {
        $this->order[$name] = $order;
    }

    public function getOrder(): array
    {
        $sort = p('sort');
        $order = p('order');
        if (0 === $order) {
            $order = SearchTypeEnum::OrderAsc->value;
        } else {
            $order = SearchTypeEnum::OrderDesc->value;
        }
        empty($sort) && $sort = SearchTypeEnum::SortId->value;
        if (!isset($this->order[$sort])) {
            $this->order[$sort] = $order;
        }

        return $this->order;
    }

    public function setPage(int $page): void
    {
        $this->page = $page;
    }

    public function getPage(): int
    {
        $page = p('page');
        empty($page) && $page = 1;

        return empty($this->page) ? $page : $this->page;
    }

    public function setPageSize(int $pageSize): void
    {
        $this->pageSize = $pageSize;
    }

    public function getPageSize(): int
    {
        $pageSize = p('page_size');
        empty($pageSize) && $pageSize = 15;

        return empty($this->pageSize) ? $pageSize : $this->pageSize;
    }

    public function getParams(): array
    {
        return $this->params;
    }

    public function setParams(string $name, mixed $value, SearchTypeEnum $op = SearchTypeEnum::EQ): void
    {
        $this->params[] = [$name, $op->value, $value];
    }

    private function parse(): void
    {
        $params = array_filter($this->searchParams, function ($key) {
            return !in_array($key, self::$keyword);
        }, ARRAY_FILTER_USE_KEY);

        $type = [];
        if (!empty($this->searchType)) {
            $type = $this->searchType->get();
        }

        if (!empty($params)) {
            foreach ($params as $param => $v) {
                if (empty($v) && SearchTypeEnum::SpecialNum->value !== $v) {
                    continue;
                }

                if (isset($type[$param])) {
                    switch ($type[$param]) {
                        case SearchTypeEnum::Like:
                            $this->params[] = [$param, SearchTypeEnum::Like->value, '%' . $v . '%'];
                            break;
                        case SearchTypeEnum::LikeSuffix:
                            $this->params[] = [$param, SearchTypeEnum::Like->value, $v . '%'];
                            break;
                        case SearchTypeEnum::LikePrefix:
                            if (is_string($v)) {
                                $v = explode(',', $v);
                            }
                            if (count($v) < 2) {
                                $v = $v[0] . ',' . $v[0];
                            } elseif (count($v) > 2) {
                                $v = $v[0] . ',' . $v[1];
                            }
                            $this->params[] = [$param, SearchTypeEnum::Like->value, '%' . $v];
                            break;
                        default:
                            $this->params[] = [$param, $type[$param]->value, $v];
                            break;
                    }
                } else {
                    $this->params[] = [$param, SearchTypeEnum::EQ->value, $v];
                }
            }
        }
    }
}